import java.util.Scanner;

/**
 * 
 * @author victor
 * 
 */
public class VerificadorSudoku {

	// tamano del sudoku (matriz cuadrada)
	private static final int TAMANO_SUDOKU = 9;
	// tamano de bloque (matriz cuadrada) del sudoku
	private static final int TAMANO_BLOQUE_SUDOKU = 3;

	/**
	 * Funcion principal
	 * 
	 * @param args
	 */
	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);
		// variable para las filas de entrada
		String linea_matriz;
		// variable para las columnas de entrada
		String[] columnas_matriz;
		// matriz con  los datos de entrada
		int[][] entrada = new int[TAMANO_SUDOKU][TAMANO_SUDOKU];
		// soluciones encontradas para el sudoku de entrada
		int soluciones_encontradas;

		try {
			// pide entrada de datos y almacena en matriz
			for (int i = 0; i < TAMANO_SUDOKU; i++) {
				// pide fila de matriz
				linea_matriz = sc.nextLine();
				// separa fila en columnas
				columnas_matriz = linea_matriz.split(" ");
				// almacena en la matriz
				for (int j = 0; j < columnas_matriz.length; j++) {
					entrada[i][j] = Integer.parseInt( columnas_matriz[j] );
				}
			}

			// busca el numero de soluciones del sudoku de entrada
			soluciones_encontradas = buscaSudokus(entrada);
			System.out.println( soluciones_encontradas );
			
		} catch (Exception e) {
			System.out.println("0");
		}
	}

	/**
	 * Crea una matriz booleana con los valores de entrada e inicializa la llamada
	 *  a la funcion recursiva desde el primer elemento
	 * @param entrada int[][] matriz con los datos de entrada
	 * @return int soluciones encontradas
	 */
	private static int buscaSudokus(int[][] entrada) {
		// matriz auxiliar representando la ocupacion de los valores iniciales
		boolean[][] ocupados = new boolean[entrada.length][entrada.length];

		// rellena la matriz auxiliar
		for (int i = 0; i < TAMANO_SUDOKU; i++) {
			for (int j = 0; j < TAMANO_SUDOKU; j++) {
				ocupados[i][j] = (entrada[i][j] != 0);
			}
		}

		// llama a la funcion recursiva desde la primera fila y columna
		// para que busque las soluciones posibles
		return sudoku(1, 1, entrada, ocupados, 0);
	}

	/**
	 * Funcion recursiva de busqueda de soluciones
	 * @param fila int fila actual a rellenar
	 * @param columna int columna actual a rellenar
	 * @param solucion int[][] datos del sudoku
	 * @param ocupados int[][] datos iniciales del sudoku
	 * @return int numero total de soluciones encontradas
	 */
	private static int sudoku(int fila, int columna, int[][] solucion, boolean[][] ocupados, int soluciones_encontradas) {
		/**
		 * Comprueba que la fila y la columna a rellenar no corresponda
		 * con un valor inicial de entrada
		 */
		if (ocupados[fila-1][columna-1] == false) {
			// recorre todos los valores posibles para esta casilla
			for (int num = 1; num <= TAMANO_SUDOKU; num++) {
				// se asigna un posible valor valido
				solucion[fila-1][columna-1] = num;

				// se comprueba que el valor asignado no se repite y es correcto
				if ( esValorNoRepetido(fila, columna, solucion)) 
				{
					// ultima fila y columna del sudoku 
					// por tanto, el sudoku se ha completado y existe solucion
					if (fila == TAMANO_SUDOKU && columna == TAMANO_SUDOKU) {
						soluciones_encontradas++;
						//imprimeSolucion(solucion);
					} 
					// ultima columna del sudoku
					else if (fila < TAMANO_SUDOKU && columna == TAMANO_SUDOKU) 
					{
						// se avanza de fila comenzando desde la primera columna
						soluciones_encontradas = sudoku( fila+1, 1, solucion, ocupados, soluciones_encontradas);
					} 
					// ultima fila del sudoku
					else if (fila <= TAMANO_SUDOKU && columna < TAMANO_SUDOKU) 
					{
						// se avanza de columna
						soluciones_encontradas = sudoku( fila, columna+1, solucion, ocupados, soluciones_encontradas);
					}

				}
				// eliminar el posible valor valido
				solucion[fila-1][columna-1] = 0;
			}
		} else {
			// ultima fila y columna del sudoku con valor inicial de entrada
			// por tanto, el sudoku se ha completado y existe solucion
			if ( fila == TAMANO_SUDOKU && columna == TAMANO_SUDOKU ) 
			{
				soluciones_encontradas++;
				//imprimeSolucion(solucion);
			} 
			// ultima columna del sudoku
			else if ( fila < TAMANO_SUDOKU && columna == TAMANO_SUDOKU ) 
			{
				// se avanza de fila comenzando desde la primera columna
				soluciones_encontradas = sudoku( fila+1, 1, solucion, ocupados,soluciones_encontradas);
			} 
			// ultima fila del sudoku
			else if ( fila <= TAMANO_SUDOKU && columna < TAMANO_SUDOKU ) 
			{
				// se avanza de columna
				soluciones_encontradas = sudoku( fila, columna+1, solucion, ocupados, soluciones_encontradas);
			}

		}
		return soluciones_encontradas;
	}

	/**
	 * Comprueba que el valor asignado a la casilla
	 * no se encuentre en la misma fila, columna o bloque
	 * @param fila int fila de la casilla a comprobar
	 * @param columna int columna de la casilla a comprobar
	 * @param solucion int[][] datos rellenados del sudoku hasta el momento
	 * @return boolean true si es valido, false si esta repetido
	 */
	private static boolean esValorNoRepetido(int fila, int columna, int[][] solucion) {
		boolean no_esta_repetido = true;
		int fila_auxiliar=1, columna_auxiliar=1;

		/**
		 * recorrido de todas las filas para una columna
		 */
		while ( fila_auxiliar <= TAMANO_SUDOKU && no_esta_repetido) {
			// comprueba que no se repita el valor dentro de la misma columna
			if ( solucion[fila-1][columna-1] == solucion[fila_auxiliar-1][columna-1] && fila_auxiliar!=fila ) {
				// valor repetido, cancela todas las comprobaciones
				no_esta_repetido = false;
			}
			// avance de fila
			fila_auxiliar++;
		}
		
		/**
		 * recorrido de todas las columnas para una fila
		 */
		while ( columna_auxiliar <= TAMANO_SUDOKU && no_esta_repetido) {
			// comprueba que no se repita dentro de la misma fila	
			if ( solucion[fila-1][columna-1] == solucion[fila-1][columna_auxiliar-1] && columna_auxiliar!=columna ) {
				// valor repetido, cancela todas las comprobaciones
				no_esta_repetido = false;
			}
			// avance de columna
			columna_auxiliar++;
		}
		
		/**
		 * recorrido de todos los elementos del mismo bloque
		 */
		// obtiene la posicion de la primera fila del bloque
		int fila_inicial_bloque = fila_auxiliar = damePosicionInicialBloque(fila);
		// obtiene la posicion de la primera fila del bloque siguiente
		int fila_final_bloque = fila_inicial_bloque + TAMANO_BLOQUE_SUDOKU;
		// obtiene la posicion de la primera columna del bloque
		int columna_inicial_bloque = columna_auxiliar = damePosicionInicialBloque(columna);
		// obtiene la posicion de la primera columna del bloque siguiente
		int columna_final_bloque = columna_inicial_bloque + TAMANO_BLOQUE_SUDOKU;
		
		// recorre todas las filas del bloque
		while ( fila_auxiliar < fila_final_bloque && no_esta_repetido) {
			// recorre todas las columnas de esta fila
			while ( columna_auxiliar < columna_final_bloque && no_esta_repetido) {
				// comprueba que no se repita dentro del mismo bloque, exceptuando la casilla a comprobar
				if ( solucion[fila-1][columna-1] == solucion[fila_auxiliar-1][columna_auxiliar-1] && fila!=fila_auxiliar && columna!=columna_auxiliar) {
					// valor repetido, cancela todas las comprobaciones
					no_esta_repetido = false;
				}
				// avance de columna
				columna_auxiliar++;
			}
			// avance de fila
			fila_auxiliar++;
			// despues de avanzar fila se comienza desde la primera columna
			columna_auxiliar = columna_inicial_bloque;
		}
		return no_esta_repetido;
	}

	/**
	 * Devuelve la posicion inicial del bloque de su fila o columna 
	 * @param fila_o_columna int fila o columna
	 * @return int primera posicion del bloque segun columna o fila
	 *                    BC1     BC2     BC3
	 *  Bloques Fila 1 |1,1 _ _|1,4 _ _|1,7 _ _|
	 *  Bloques Fila 1 |_   _ _|_   _ _|_   _ _|
	 *  Bloques Fila 1 |_   _ _|_   _ _|_   _ _|
	 *  
	 *  Bloques Fila 2 |4,1 _ _|4,4 _ _|4,7 _ _|
	 *  Bloques Fila 2 |_   _ _|_   _ _|_   _ _|
	 *  Bloques Fila 2 |_   _ _|_   _ _|_   _ _|
	 *  
	 *  Bloques Fila 3 |7,1 _ _|7,4 _ _|7,7 _ _|
	 *  Bloques Fila 3 |_   _ _|_   _ _|_   _ _|
	 *  Bloques Fila 3 |_   _ _|_   _ _|_   _ _|
	 * 
	 */
	private static int damePosicionInicialBloque(int fila_o_columna) {
		int bloque, posicion_inicial_bloque = 0;
		
		// obtiene el bloque
		bloque = (fila_o_columna % TAMANO_BLOQUE_SUDOKU == 0) ? (fila_o_columna / TAMANO_BLOQUE_SUDOKU) : ((fila_o_columna / TAMANO_BLOQUE_SUDOKU) + 1);
		
		// asignar primera posicion de bloque al que pertenece
		switch ( bloque ) {
			case 1:
				// posicion inicial de la primer fila o columna de bloques
				posicion_inicial_bloque = 1;
				break;
			case 2:
				// posicion inicial de la segunda fila o columna de bloques
				posicion_inicial_bloque = 4;
				break;
			case 3:
				// posicion inicial de la  tercera fila o columna de bloques
				posicion_inicial_bloque = 7;
				break;
		}
		return posicion_inicial_bloque;
	}

	/**
	 * Pinta la solucion del sudoku por pantalla
	 * @param solucion int[][] datos completos de sudoku
	 */
	private static void imprimeSolucion(int[][] solucion) {
		for (int i = 0; i < TAMANO_SUDOKU; i++) 
		{
			for (int j = 0; j < TAMANO_SUDOKU; j++) 
			{
				if (j!=0)
				{
					System.out.print(" ");
				}
				System.out.print(solucion[i][j]);
			}
			System.out.println("");
		}
		System.out.println("-------------------");
	}

}
